/*
 * MemoryVisualizer.java
 *
 * Created on May 8, 2006, 7:52 PM
 */

package emr.jvm.visualization;

import java.awt.*;
import java.nio.ByteBuffer;
import javax.swing.JViewport;

/**
 *
 * @author  Ross
 */
public class MemoryVisualizer extends javax.swing.JFrame implements Runnable {

    /* Memory tags for visualization purposes */
    public static final Color JVM_CORE = Color.red; // red
    //public static final Color OBJECT = Color.orange; // green
    //public static final Color INSTANCE = Color.green; // green
    //public static final Color ARRAY = Color.magenta; // purple
    public static final Color OBJECT = new Color(242, 166, 96); // green
    public static final Color INSTANCE = new Color(238, 140, 51); // green
    public static final Color ARRAY = new Color(200, 122, 19); // purple
    public static final Color INTERRUPT_VECTOR = new Color(125, 100, 200);

    public static final Color FRAME = Color.cyan; // blue
    public static final Color EMPTY = Color.lightGray; // background
    public static final Color MM    = Color.YELLOW; // memory management
    public static final Color NVMDATA = Color.cyan;
    
    
    /** Static variable polled by all instances of MemoryVisualizer to control
     * whether to display output or not.
     */
    public static boolean showOutput = true;
    
    
    // references to the arrays in the Memory object
    private ByteBuffer memory;
    private Color[] tags;
    
    private int baseAddress;
    
    /** Creates new form MemoryVisualizer */
    public MemoryVisualizer(String name, ByteBuffer memory_, Color[] tags_, int baseAddress_) {
        memory = memory_;
        tags = tags_;
        baseAddress = baseAddress_;

        if (memory.capacity() != tags.length){
            System.out.println("Arrays not same length");
            System.exit(1);
        }
        
        if (memory.capacity() % 4 != 0){
            System.out.println("Arrays not multiple of 4");
            System.exit(1);
        }

        initComponents();
        initCustomComponents();
        
        setTitle(name);
        setVisible(true);

        
        //Thread t = new Thread(this);
        //t.setPriority(1);
        //t.start();
        
    }
    
    
    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    // <editor-fold defaultstate="collapsed" desc=" Generated Code ">//GEN-BEGIN:initComponents
    private void initComponents()
    {
        memoryPanel = new javax.swing.JPanel();
        zoomInScrollPanel = new javax.swing.JScrollPane();
        zoomInPanel = new emr.jvm.visualization.ZoomInPanel();
        jLabel1 = new javax.swing.JLabel();
        jLabel2 = new javax.swing.JLabel();
        jPanel1 = new javax.swing.JPanel();
        zoomOutScrollPanel = new javax.swing.JScrollPane();
        zoomOutPanel = new emr.jvm.visualization.ZoomOutPanel();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setTitle("MemoryVisualizer");
        memoryPanel.setBorder(javax.swing.BorderFactory.createTitledBorder("Details"));
        org.jdesktop.layout.GroupLayout zoomInPanelLayout = new org.jdesktop.layout.GroupLayout(zoomInPanel);
        zoomInPanel.setLayout(zoomInPanelLayout);
        zoomInPanelLayout.setHorizontalGroup(
            zoomInPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(0, 180, Short.MAX_VALUE)
        );
        zoomInPanelLayout.setVerticalGroup(
            zoomInPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(0, 252, Short.MAX_VALUE)
        );
        zoomInScrollPanel.setViewportView(zoomInPanel);

        jLabel1.setText("Address");

        jLabel2.setText("Contents");

        org.jdesktop.layout.GroupLayout memoryPanelLayout = new org.jdesktop.layout.GroupLayout(memoryPanel);
        memoryPanel.setLayout(memoryPanelLayout);
        memoryPanelLayout.setHorizontalGroup(
            memoryPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(org.jdesktop.layout.GroupLayout.TRAILING, memoryPanelLayout.createSequentialGroup()
                .add(19, 19, 19)
                .add(jLabel1)
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED, 56, Short.MAX_VALUE)
                .add(jLabel2)
                .add(24, 24, 24))
            .add(org.jdesktop.layout.GroupLayout.TRAILING, zoomInScrollPanel, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 182, Short.MAX_VALUE)
        );
        memoryPanelLayout.setVerticalGroup(
            memoryPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(memoryPanelLayout.createSequentialGroup()
                .add(memoryPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
                    .add(jLabel2)
                    .add(jLabel1))
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                .add(zoomInScrollPanel, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 254, Short.MAX_VALUE))
        );

        jPanel1.setBorder(javax.swing.BorderFactory.createTitledBorder("Overview"));
        org.jdesktop.layout.GroupLayout zoomOutPanelLayout = new org.jdesktop.layout.GroupLayout(zoomOutPanel);
        zoomOutPanel.setLayout(zoomOutPanelLayout);
        zoomOutPanelLayout.setHorizontalGroup(
            zoomOutPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(0, 127, Short.MAX_VALUE)
        );
        zoomOutPanelLayout.setVerticalGroup(
            zoomOutPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(0, 261, Short.MAX_VALUE)
        );
        zoomOutScrollPanel.setViewportView(zoomOutPanel);

        org.jdesktop.layout.GroupLayout jPanel1Layout = new org.jdesktop.layout.GroupLayout(jPanel1);
        jPanel1.setLayout(jPanel1Layout);
        jPanel1Layout.setHorizontalGroup(
            jPanel1Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(zoomOutScrollPanel, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 95, Short.MAX_VALUE)
        );
        jPanel1Layout.setVerticalGroup(
            jPanel1Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(jPanel1Layout.createSequentialGroup()
                .addContainerGap()
                .add(zoomOutScrollPanel))
        );

        org.jdesktop.layout.GroupLayout layout = new org.jdesktop.layout.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(layout.createSequentialGroup()
                .addContainerGap()
                .add(jPanel1, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                .add(memoryPanel, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(layout.createSequentialGroup()
                .addContainerGap()
                .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                    .add(jPanel1, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .add(memoryPanel, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
        );
        pack();
    }// </editor-fold>//GEN-END:initComponents
    
    
    private void initCustomComponents() {
        //memoryPanel.add(new ZoomOutPanel(), org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE);
     
        Insets insets = zoomOutScrollPanel.getInsets();
        zoomOutPanel.setPreferredSize(new Dimension(zoomOutScrollPanel.getWidth() - insets.left - insets.right, memory.capacity() / 4));
        
        insets = zoomInScrollPanel.getInsets();
        zoomInPanel.setPreferredSize(new Dimension(zoomInScrollPanel.getWidth() - insets.left - insets.right, ZoomInPanel.boxHeight * memory.capacity() / 4));

        zoomOutPanel.setMemory(memory, tags);
        zoomInPanel.setMemory(memory, tags, baseAddress);
        
    }

    /** Initiates painting of the zoomPanels due to a memory update 
     * Specifies an index that the repaint will focus on.
     * If the index is not in the viewable area, then the viewing area is centered on the index.
     * Otherwise, the viewing area is not modified and the specified index is highlighted.
     */
     
    public void repaintZoomPanels(int index) 
    {
        repaintZoomPanelsInternal(index);
    }
    
    private void repaintZoomPanelsInternal(int index_) 
    {
        // don't repaint if showOutput is false
        if( showOutput == false )
            return;
        
        // need to know what is visible
        
        JViewport view = zoomInScrollPanel.getViewport();
        
        Rectangle newView = view.getViewRect();
        
        Insets insets = zoomInPanel.getInsets();
        int width = zoomInPanel.getWidth() - insets.right - insets.left;
        int height = getHeight() - insets.top - insets.bottom;

        int boxHeight = zoomInPanel.getBoxHeight();
        
        // if index_ is within viewable area, do nothing
        //if( index_ * boxHeight )
        //newView.setRect(0,, width, height);
        zoomInPanel.setVisibleIndex(index_);
        zoomOutPanel.setVisibleIndex(index_);
        //newView.x = zoomInPanel.;
        //zoomInPanel.scrollRectToVisible(newView);

        //try {
            //java.awt.EventQueue.invokeLater(new Runnable() {
            //    public void run() {
                    zoomOutPanel.repaint();
                    zoomInPanel.repaint();
            //    }
            //});
        //} catch (Exception e) {
        //    System.out.println(e.getMessage());
        //    System.exit(1);
        //}
        //zoomOutPanel.repaint();
        //zoomInPanel.repaint();        
    }
    
    public void repaintZoomPanels()
    {
        repaintZoomPanels(0);
    }
    
    public void repaintZoomPanels(int index, int size) 
    {
        repaintZoomPanels(index);
    }
    
    
    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                int size = 1024;
                byte[] bytes = new byte[size];
                Color[] colors = new Color[size];
                
                for (int i = 0; i < size; i++)
                {
                    bytes[i] = (byte)i;
                    Color c;
                    if (i % 4 == 0)
                        c = Color.magenta;
                    else if (i % 4 == 1)
                        c = Color.cyan;
                    else if (i % 4 == 2)
                        c = Color.pink;
                    else
                        c = Color.orange;
                    
                    colors[i] = c;
                }
                MemoryVisualizer mv = new MemoryVisualizer("Test", ByteBuffer.wrap(bytes), colors, 0x20000000);
                mv.setVisible(true);
                
            }
        });
    }
    
    
    
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JPanel memoryPanel;
    private emr.jvm.visualization.ZoomInPanel zoomInPanel;
    private javax.swing.JScrollPane zoomInScrollPanel;
    private emr.jvm.visualization.ZoomOutPanel zoomOutPanel;
    private javax.swing.JScrollPane zoomOutScrollPanel;
    // End of variables declaration//GEN-END:variables

    public void run() {
    
        while (true)
        {
            try {
                repaintZoomPanelsInternal(0);
                Thread.sleep(100);
            } catch (InterruptedException e)
            {
            
            }
        }
    }
    
}
